import fetch from 'isomorphic-fetch';
import qs from 'qs';
import codes from './codes';
import urlJoin from 'url-join';
import config from '../config';
import Cookies from 'js-cookie';

import { isBrowser } from './utils';
import FileSlice from './FileSlice';

function errTip(msg) {
	// 统一错误处理, 不影响抛出错误
	if (global.VUE_INSTANCE && global.location) {
		VUE_INSTANCE.$message && VUE_INSTANCE.$message.error(msg);
	}
}

const _fetch = async function(path, { headers = {}, ...opts }) {
	let token;
	if (isBrowser) {
		if (global.TOKEN_LOCAL) {
			token = localStorage.token;
			headers.ClientPlatform = 'app';
		} else {
			if (document.cookie) {
				token = Cookies.get('token');
				if (token) {
					sessionStorage.token = token;
					Cookies.remove('token', {
						domain: global.restUrl_system.replace('http://', '.')
					});
				}
			}
			if (!token) {
				token = sessionStorage.token;
			}
		}
	} else {
		token = config.token;
	}
	// alert(token);

	headers.Authorization = `Bearer ${token}`;

	//C端需要的headers
	headers.AuthPlatform = '';
	headers.AuthSource = '';
	headers['X-Requested-With'] = 'XMLHttpRequest';
	if (!/^https?\:/.test(path)) {
		path = urlJoin(process.env.VUE_APP_BASE_URL, path);
	}
	return fetch(path, {
		headers,
		...opts,
		mode: 'cors'
	})
		.then((res) => {
			if (res.status >= 400) {
				const err = new Error(codes.E_NETWORK);
				err.payload = {
					status: false,
					code: 'E_NETWORK',
					message: err.message,
					msg: err.message,
					errors: [ res.status ]
				};
				errTip(err.message);
				throw err;
			}
			return res.text();
		})
		.then((payload) => {
			payload = JSON.parse(payload);
			if (payload.code == 0 && payload.data) {
				const { data, code, msg } = payload;
				if (data.hasOwnProperty('total') && data.hasOwnProperty('list')) {
					return {
						code,
						msg,
						data: data.list,
						page: {
							offset: data.pageSize,
							total: data.total,
							num: data.pageNum
						}
					};
				}
				return payload;
			}
			if (payload.code === 20401) {
				location.href = process.env.NODE_ENV == 'production' ? '/dist/' : '/';
				const err = new Error(payload.msg);
				err.payload = payload;
				err.payload.message = payload.msg;
				throw err;
			}
			if (payload.code != 0) {
				const err = new Error(payload.msg);
				err.payload = payload;
				err.payload.message = payload.msg;
				throw err;
			}
			return payload;
		});
};

function setHeaders({ pageStart = null, pageOffset, pageNum = 0 }) {
	const headers = {
		'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
		// 'Content-Type': 'application/json',
		// 'Access-Control-Allow-Origin': '*',
		// 'Access-Control-Allow-Headers': 'X-Requested-With,Content-Type',
		// 'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS'
	};
	if (pageStart !== null) {
		headers.pageNum = (pageStart || 0) / pageOffset + 1;
		headers.pageSize = pageOffset;
		// headers.PageOffset = pageOffset / pageStart + 1;
	} else if (pageNum > 0) {
		headers.pageNum = pageNum;
		headers.pageSize = pageOffset;
		// headers.PageStart = (pageNum - 1) * pageOffset;
		// headers.PageOffset = pageOffset;
	}
	return headers;
}

//get请求
export const request_get = (path, { pageStart = null, pageOffset = 10, pageNum, ...data } = {}) => {
	const headers = setHeaders({
		pageStart,
		pageOffset,
		pageNum
	});
	if (headers.pageSize) {
		data['pageNum'] = headers.pageNum;
		data['pageSize'] = headers.pageSize;
	}
	return _fetch(
		path +
			qs.stringify(data, {
				addQueryPrefix: true
			}),
		{
			method: 'GET',
			headers
		}
	);
};

//post请求
export const request_post = (path, { pageStart, pageOffset = 10, pageNum, ...data } = {}) => {
	const headers = setHeaders({
		pageStart,
		pageOffset,
		pageNum
	});
	return _fetch(path, {
		method: 'POST',
		headers,
		body: qs.stringify(data, {
			skipNulls: true,
			arrayFormat: 'repeat'
		})
	});
};

//put请求
export const request_put = (path, { pageStart, pageOffset = 10, pageNum, ...data } = {}) => {
	const headers = setHeaders({ pageStart, pageOffset, pageNum });
	return _fetch(path, {
		method: 'PUT',
		headers,
		body: qs.stringify(data, {
			strictNullHandling: true
		})
	});
};

//delete请求
export const request_delete = (path, data = {}) => {
	return _fetch(
		path +
			qs.stringify(data, {
				addQueryPrefix: true,
				arrayFormat: 'repeat'
			}),
		{
			method: 'DELETE'
		}
	);
};

/**
 * 新上传文件接口
 * @param {*} file
 * @param {*} callback 回调函数, 可选, 返回上传进度, 参数只有一个num
 */
export async function uploadFile(file, callback) {
	let data = {};
	try {
		let res = await request_post(`/common/api/files/upload_task?r=${Math.random()}`);
		data.task_id = res.data.task_id;
		data.is_chunk = true;
	} catch (error) {
		throw new Error('获取task_id失败!');
	}
	return splice2({
		file,
		data,
		fileSlice: new FileSlice(file),
		callback
	});
}

async function splice2({ file, data, fileSlice, callback }) {
	const file_data = fileSlice.next();
	const form_data = new FormData();
	form_data.append('task_id', data.task_id);
	form_data.append('name', file.name);
	form_data.append('size', file.size);
	form_data.append('type', file.type);
	form_data.append('file', file_data.chunk);
	form_data.append('chunks', file_data.total);
	form_data.append('chunk', file_data.count);
	form_data.append('chunk_size', file_data.size);
	let res = await _fetch(`/common/api/files/upload?r=${Math.random()}`, {
		method: 'POST',
		body: form_data
	});
	if (typeof callback == 'function') {
		callback(res.data.chunks_completed_percent);
	}
	if (res.code === '20201') {
		return res;
	}
	if (fileSlice.hasNext()) {
		console.log('uploading...');
		return splice2({
			file,
			data,
			fileSlice,
			callback
		});
	} else {
		console.log('upload end');
	}
}

//getProgress
export async function request_progress(path, callback = () => {}) {
	return await _fetch(path, {
		method: 'GET'
	}).then((res) => {
		if (res.data.number >= 100) {
			res.data.number = 100;
			callback(res);
			return res;
		} else {
			callback(res);
			if (res.data.number < 100) {
				return setTimeout(() => {
					request_progress(path, callback);
				}, 500);
			} else {
				throw new Error('获取进度失败');
			}
		}
	});
}

// 不分片上传文件
const fileUpload = (path, file) => {
	const form_data = new FormData();
	form_data.append('name', file.name);
	form_data.append('size', file.size);
	form_data.append('type', file.type);
	form_data.append('file', file);
	form_data.append('chunks', 1);
	form_data.append('chunk', 0);
	form_data.append('chunk_size', file.size);
	console.log('new data');
	console.log(form_data);
	// 多文件上传, 不区分链接, 会合并请求, 导致失败
	return _fetch(path + `?r=${Math.random(5)}`, {
		method: 'POST',
		body: form_data
	});
};

//分片上传
const splice = async (path, { file, data } = data, upload, callback) => {
	const form_data = new FormData();
	form_data.append('task_id', data.task_id);
	form_data.append('name', file.name);
	form_data.append('size', file.size);
	form_data.append('type', file.type);
	const file_data = upload.next();
	form_data.append('file', file_data.chunk);
	form_data.append('chunks', file_data.total);
	form_data.append('chunk', file_data.count);
	form_data.append('chunk_size', file_data.size);

	return await _fetch(path + `?r=${Math.random(5)}`, {
		method: 'POST',
		body: form_data
	}).then((res) => {
		if (res.code == '20201') {
			return res;
		} else {
			if (typeof callback == 'function') {
				request_get('/common/api/files/upload_task/' + data.task_id).then((task) => {
					callback(task.data.chunks_completed_percent);
				});
			}
			if (upload.hasNext()) {
				return splice(
					path,
					{
						file,
						data
					},
					upload,
					callback
				);
			} else {
				throw new Error('分片错误');
			}
		}
	});
};

//formData
export const request_file = (path, { file, data = {} } = data, callback) => {
	if (data.is_chunk) {
		const upload = new FileSlice(file, data.size);
		return splice(
			path,
			{
				file,
				data
			},
			upload,
			callback
		);
	} else {
		return fileUpload(path, file);
	}
};

export function getFullPath(path) {
	if (path.indexOf('/system/') == 0) {
		path = urlJoin(global.restUrl_system, path);
	} else if (path.indexOf('/common/') == 0) {
		path = urlJoin(global.restUrl_common, path);
	} else {
		path = urlJoin(global.restUrl, path);
	}
	return path;
}
